#include <iostream>
#include <cassert>

using namespace std;

/*
int add(int a, int b){
    cout << "int add(int a, int b)" << endl;
    return a + b;
}

double add(double a, double b){
    cout << "double add(double a, double b)" << endl;
    return a + b;
}

int main(){
    add(1,2);
    add(1.1,2.2);
    return 0;
}
*/

/*
int main(){
    int i = 0;
    int& k = i;

    int j = i;

    cout << &i << endl;
    cout << &k << endl;
    cout << &j << endl;

    k++;

    cout << i << endl;

    return 0;
}
*/

/*
void Swap(int& x, int& y){
    int tmp = x;
    x = y;
    y = tmp;
}

int main(){
    int i = 0, j = 1;
    Swap(i,j);
    cout << i << endl;
    cout << j << endl;
}
*/

/*
typedef struct Node{
    struct Node* next;
    int val;
}Node, *PNode;

//原本需要传二级指针
*/
/*
void PushBack(Node** pHead, int x){
    Node* newNode = (Node*) malloc(sizeof(Node));
    if(*pHead == nullptr)
        *pHead = newNode;
}
*//*


//void PushBack(PNode& pHead, int x)
void PushBack(Node*& pHead, int x){
    Node* newNode = (Node*) malloc(sizeof(Node));
    if(pHead == nullptr)
        pHead = newNode;
}

int main(){
    Node *pList = nullptr;
    PushBack(pList,1);
    return 0;
}
*/

/*
int& Add(int a, int b)
{
	static int c = a + b;//要出了作用域还在的才可以，否则非法访问
	return c;
}

int main()
{
	int& ret = Add(1, 2);
	Add(3, 4);
	cout << "Add(1, 2) is :" << ret << endl;
	cout << "Add(1, 2) is :" << ret << endl;

	return 0;
}
*/

//引用特性
//在定义时必须初始化
//一个变量可以有多个引用
//一旦引用一个实体，就不能再引用其他实体

//引用：
//做参数：输出型参数（需要形参的改变来影响实参）
//做返回值：减少拷贝，调用者可以修改返回对象

/*
#define N 10
typedef struct Array{
    int a[N];
    int size;
}AY;

 //引用返回（出了作用域没有被销毁）
 //1.减少拷贝
 //2.调用者可以修改返回对象

 //返回第i个位置的别名
int& PosAt(AY& ay,int i){
    assert(i < N);
    return ay.a[i];
}

int main(){
    AY ay;
    for (int i = 0; i < N; ++i) {
        PosAt(ay,i) = i*10;//还可以直接修改
    }
    for (int i = 0; i < N; ++i) {
        cout << PosAt(ay,i) << " ";
    }
    cout << endl;
    return 0;
}
*/

/*
#define N 10
typedef struct Array{
    int& at(int i){
        assert(i < N);
        return a[i];
    }
    int a[N];
    int size;
}AY;

int main(){
    AY ay;
    for (int i = 0; i < N; ++i) {
        ay.at(i) = i;
    }
    for (int i = 0; i < N; ++i) {
        cout << ay.at(i) << " ";
    }
}
*/

//如果函数返回时，出了函数作用域，返回对象还在，可以使用引用返回
//eg.静态、全局、上一层栈帧、malloc的
//如果已经还给系统了，则必须使用传值返回

//指针和引用，赋值|初始化：权限可以缩小，但是不能放大

/*
int main(){
    int a = 1;
    int& b = a;
    //权限放大，wrong
    const int* p1;
    int*& p2 = p1;
    //权限保持
    const int c = 2;
    const int& d = c;
    const int*pc = &c;
    const int*&pd = pc;
    //权限缩小
    int l = 0;
    const int&m = l;
}
*/

int main(){
    int i = 10;
    //强制类型转换时，也产生一个临时变量，不是将i转换
    cout << (double)i << endl;//显式
    double dd = i;//隐式

    //不加const会使得权限放大：i给rd的时候，产生临时变量具有常性
    const double &rd = i;
}

#define ADD(x,y) ((x)+(y))

//宏缺点：
//1.不能调试
//2.没有类型安全的检查
//3.有些场景下非常复杂，容易出错

//C++推荐：
//const和enum替代宏常量
//inline替代宏函数

inline int Add(int x, int y){
    int z = x + y;
    return z;
}

/*
int main(){
    int ret = Add(1,2);
    cout << ret << endl;
    int a = 6;
    int b = 8;
    const int* p1 = &a;
    p1 = &b;
    //*p1 = 3;//不可以
    int* const p2 = &a;
    *p2 = 9;
    //p2 = &b;//不可以
    return 0;
}
*/
